package hnpush

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"

	"go-share/logging"
	. "go-share/models"
	"go-share/models/channel"
	"go-share/models/common"
)

type Hnpush struct {
}

const (
	HNPUSH_PRODUCTID = 1
	HTTP_TIMEOUT     = 3

/*	USER_ADD_TAG      = "/push/userAddTag.jspa"
	USER_DEL_TAG      = "/push/userDelTag.jspa"
	SEND_TAG_MESSAGE  = "/push/sendTagMessage.jspa"
	SEND_USER_MESSAGE = "/push/sendUserMessage.jspa"
	USER_DEL_ALL_TAG  = "/push/userDelTagAll.jspa"*/
)

//var pushHostStr string
var pushApi *HnPushApiStruct

type HnPushApiStruct struct {
	Host            string
	UserAddTag      string
	UserDelTag      string
	SendTagMessage  string
	SendUserMessage string
	UserDelAllTag   string
	UserLogin       string
	UserLogout      string
	OpenApp         string
}

type HnpushTarget struct {
	UserID    string `json:"userId"`    // 用户ID
	TagName   string `json:"tagName"`   // tag名字
	ProductId int    `json:"productId"` // 产品ID
}

type HnpushMessage struct {
	Title         string                 `json:"title"`
	TagName       string                 `json:"tagName"`           // tag名字
	Content       string                 `json:"content"`           // 内容
	ExtendContent map[string]interface{} `json:"pushExtendContent"` //扩展内容
	ProductId     int                    `json:"productId"`         // 产品ID
}

type HnpushMemberMessage struct {
	Title         string                 `json:"title"`
	MemberId      string                 `json:"userId"`            // 用户id
	Content       string                 `json:"content"`           // 内容
	ExtendContent map[string]interface{} `json:"pushExtendContent"` //扩展内容
	ProductId     int                    `json:"productId"`         // 产品ID
}

//删除该用户所有标签 wdk 20170929 add
type HnDelUserAllTarget struct {
	MemberId  string `json:"userId"`    // 用户ID
	ProductId int    `json:"productId"` // 产品ID
}

type hnData struct {
	Msg string `json:"msg"`
}
type HnpushRes struct {
	Code int    `json:"code"`
	Data hnData `json:"data"`
}

func NewHnpush(api *HnPushApiStruct) {
	pushApi = api
	logging.Debug("NewHnpush  host:%v; UserAddTag:%v; UserDelTag:%v; SendTagMessage:%v; SendUserMessage:%v; UserDelAllTag:%v;",
		pushApi.Host, pushApi.UserAddTag, pushApi.UserDelTag, pushApi.SendTagMessage, pushApi.SendUserMessage, pushApi.UserDelAllTag)
}

// 添加成员标签
func AddMemberTag(target HnpushTarget) (*HnpushRes, error) {
	data, err := json.Marshal(target)
	if err != nil {
		logging.Error("Error AddMemberTag json %v", err)
		return nil, err
	}

	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.UserAddTag)
	logging.Debug("AddMemberTag url:%v;data:%v;", urlStr, string(data))
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(string(data)))
	if err != nil {
		logging.Error("PostUrl AddMemberTag Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("AddMemberTag ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("json Unmarshal Error | %v", err)
		return nil, err
	}

	return &mess, nil
}

// 移除成员标签
func RemoveMemberTag(target HnpushTarget) (*HnpushRes, error) {
	data, err := json.Marshal(target)
	if err != nil {
		logging.Error("Error RemoveMemberTag json %v", err)
		return nil, err
	}

	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.UserDelTag)
	logging.Debug("RemoveMemberTag url:%v;data:%v;", urlStr, string(data))
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(string(data)))
	if err != nil {
		logging.Error("PostUrl RemoveMemberTag Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("RemoveMemberTag ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("RemoveMemberTag json Unmarshal Error | %v", err)
		return nil, err
	}

	return &mess, nil
}

//发送推送内容
func PushMessage(message HnpushMessage) (*HnpushRes, error) {
	data, err := json.Marshal(message)
	if err != nil {
		logging.Error("Error PushMessage json %v", err)
		return nil, err
	}

	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.SendTagMessage)
	logging.Debug("PushMessage url:%v;data:%v;", urlStr, string(data))
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(string(data)))
	if err != nil {
		logging.Error("PostUrl PushMessage Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("PushMessage ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("PushMessage json Unmarshal Error | %v", err)
		return nil, err
	}
	logging.Debug("PushMessage code:%v, msg:%v;", mess.Code, mess.Data.Msg)

	return &mess, nil
}

// 移除成员全部标签
func RemoveMemberAllTag(target HnDelUserAllTarget) (*HnpushRes, error) {
	data, err := json.Marshal(target)
	if err != nil {
		logging.Error("Error RemoveMemberAllTag json %v", err)
		return nil, err
	}

	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.UserDelAllTag)
	logging.Debug("RemoveMemberAllTag url:%v;data:%v;", urlStr, string(data))
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(string(data)))
	if err != nil {
		logging.Error("PostUrl RemoveMemberAllTag Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("RemoveMemberAllTag ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("RemoveMemberAllTag json Unmarshal Error | %v", err)
		return nil, err
	}

	return &mess, nil
}

//给单个用户推送消息 wdk 20170928 add
func PushMemberMessage(message HnpushMemberMessage) (*HnpushRes, error) {
	data, err := json.Marshal(message)
	if err != nil {
		logging.Error("Error PushMemberMessage json %v", err)
		return nil, err
	}

	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.SendUserMessage)
	logging.Debug("PushMemberMessage url:%v;data:%v;", urlStr, string(data))
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(string(data)))
	if err != nil {
		logging.Error("PostUrl PushMemberMessage Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("PushMemberMessage ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("PushMemberMessage json Unmarshal Error | %v", err)
		return nil, err
	}
	logging.Debug("PushMemberMessage code:%v, msg:%v;", mess.Code, mess.Data.Msg)

	return &mess, nil
}

//登录接口 wdk 20171009 add
func PushMemberLogin(dataJson string) (*HnpushRes, error) {
	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.UserLogin)
	logging.Debug("PushMemberLogin url:%v;data:%v;", urlStr, dataJson)
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(dataJson))
	if err != nil {
		logging.Error("PostUrl PushMemberLogin Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("PushMemberLogin ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("PushMemberLogin json Unmarshal Error | %v", err)
		return nil, err
	}
	logging.Debug("PushMemberLogin code:%v, msg:%v;", mess.Code, mess.Data.Msg)

	return &mess, nil
}

//登出接口 wdk 20171009 add
func PushMemberLogout(dataJson string) (*HnpushRes, error) {
	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.UserLogout)
	logging.Debug("PushMemberLogout url:%v;data:%v;", urlStr, dataJson)
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(dataJson))
	if err != nil {
		logging.Error("PushMemberLogout PostUrl Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("PushMemberLogout ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("PushMemberLogout json Unmarshal Error | %v", err)
		return nil, err
	}
	logging.Debug("PushMemberLogout code:%v, msg:%v;", mess.Code, mess.Data.Msg)

	return &mess, nil
}

//打开app接口 wdk 20171010 add
func PushOpenApp(dataJson string) (*HnpushRes, error) {
	urlStr := fmt.Sprintf("%v%v", pushApi.Host, pushApi.OpenApp)
	logging.Debug("PushOpenApp url:%v;data:%v;", urlStr, dataJson)
	resp, err := NewHttpClient().Post(urlStr, "application/json", strings.NewReader(dataJson))
	if err != nil {
		logging.Error("PushOpenApp PostUrl Error | %v", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error("PushOpenApp ReadAll Body Error | %v", err)
		return nil, err
	}
	var mess HnpushRes
	err = json.Unmarshal(body, &mess)
	if err != nil {
		logging.Error("PushOpenApp json Unmarshal Error | %v", err)
		return nil, err
	}
	logging.Debug("PushOpenApp code:%v, msg:%v;", mess.Code, mess.Data.Msg)

	return &mess, nil
}

//**********************************************
//将用户注册到hnpush所有的标签 wdk 20170928 add
func RegisterHnpush(memberId int64) {
	if memberId <= 0 {
		logging.Error("Invild member ID | %d", memberId)
	}
	m := common.NewMember()
	if err := m.GetSingle(memberId); err != nil {
		logging.Error("Get member Single |%v", err)
		return
	}
	memberIdStr := IDEncrypt(m.ID)

	var delAllTarget HnDelUserAllTarget
	delAllTarget.MemberId = memberIdStr
	delAllTarget.ProductId = HNPUSH_PRODUCTID
	//移除该用户所有标签
	if ret, err := RemoveMemberAllTag(delAllTarget); err != nil {
		logging.Error("RegisterHnpush RemoveMemberAllTag | %v", err)
	} else {
		logging.Debug("RegisterHnpush RemoveMemberAllTag code:%v; msg:%v;", ret.Code, ret.Data.Msg)
	}

	// 添加自己的用户组
	var target HnpushTarget
	target.UserID = memberIdStr
	target.TagName = fmt.Sprintf(JPUSH_TAG_GROUP, IDEncrypt(m.GroupID))
	target.ProductId = HNPUSH_PRODUCTID
	if ret, err := AddMemberTag(target); err != nil {
		logging.Error("RegisterHnpush add oneself group | %v", err)
	} else {
		logging.Debug("RegisterHnpush AddMemberTag groups code:%v; msg:%v;", ret.Code, ret.Data.Msg)
	}

	// 添加自己所订的频道
	ch := channel.NewChannel()
	ids := ch.InitNotifyChannelCache(memberId)
	for _, id := range ids {
		target.UserID = memberIdStr
		target.TagName = fmt.Sprintf(JPUSH_TAG_GROUP, IDEncrypt(id))
		target.ProductId = HNPUSH_PRODUCTID
		if ret, err := AddMemberTag(target); err != nil {
			logging.Error("RegisterHnpush add channel tags | %v", err)
		} else {
			logging.Debug("RegisterHnpush AddMemberTag channel code:%v; msg:%v;", ret.Code, ret.Data.Msg)
		}
	}
}

//*********************************************
//NewHttpClient
func NewHttpClient() *http.Client {
	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				conn, err := net.DialTimeout(netw, addr, time.Second*HTTP_TIMEOUT)
				if err != nil {
					return nil, err
				}
				conn.SetDeadline(time.Now().Add(time.Second * HTTP_TIMEOUT))
				return conn, nil
			},
			ResponseHeaderTimeout: time.Second * HTTP_TIMEOUT,
		},
	}
	return client
}
